package aceim.protocol.snuk182.xmpp.common;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;
import org.jivesoftware.smackx.filetransfer.FileTransferListener;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
import aceim.api.dataentity.Buddy;
import aceim.api.dataentity.FileInfo;
import aceim.api.dataentity.FileMessage;
import aceim.api.dataentity.FileProgress;
import aceim.api.utils.Logger;
import aceim.api.utils.Logger.LoggerLevel;
import aceim.api.utils.Utils;
public class XMPPFileTransferListener extends XMPPListener implements FileTransferListener {
private FileTransferManager mFileTransferManager;
private final Map<Long, FileTransferRequest> fileTransfers = Collections.synchronizedMap(new HashMap<Long, FileTransferRequest>());
public XMPPFileTransferListener(XMPPServiceInternal service) {
super(service);
}
@Override
public void fileTransferRequest(FileTransferRequest request) {
Logger.log("incoming file " + request.getFileName() + " from " + request.getRequestor(), LoggerLevel.VERBOSE);
fileTransfers.put(Long.valueOf(request.getStreamID().hashCode()) , request);
FileInfo fi = new FileInfo(getInternalService().getService().getServiceId());
fi.setFilename(request.getFileName());
fi.setSize(request.getFileSize());
FileMessage fm = new FileMessage(getInternalService().getService().getServiceId(), getInternalService().getService().getEntityAdapter().normalizeJID(request.getRequestor()), Arrays.asList(fi));
fm.setMessageId(request.getStreamID().hashCode());
getInternalService().getService().getCoreService().message(fm);
}
void fileRespond(final FileMessage fileMessage, final Boolean accept) {
FileTransferRequest request = fileTransfers.remove(fileMessage.getMessageId());
if (request != null) {
if (accept) {
Runnable r = new IncomingFileRunnable(fileMessage.getContactUid(), request);
Executors.defaultThreadFactory().newThread(r).start();
} else {
request.reject();
}
} else {
Logger.log("No file message to respond " + fileMessage.getMessageId(), LoggerLevel.INFO);
}
}
long sendFile(final String receiverJid, final List<File> files) {
final OutgoingFileTransfer transfer = mFileTransferManager.createOutgoingFileTransfer(receiverJid);
Runnable r = new OutgoingFileRunnable(files, transfer, receiverJid);
Executors.defaultThreadFactory().newThread(r).start();
return transfer.getStreamID().hashCode();
}
/**
* @return the mFileTransferManager
*/
public FileTransferManager getFileTransferManager() {
return mFileTransferManager;
}
/**
* @param mFileTransferManager the mFileTransferManager to set
*/
public void setFileTransferManager(FileTransferManager mFileTransferManager) {
this.mFileTransferManager = mFileTransferManager;
}
private class OutgoingFileRunnable implements Runnable {
private final List<File> files;
private final OutgoingFileTransfer transfer;
private final String receiverJid;
private OutgoingFileRunnable(List<File> files, OutgoingFileTransfer transfer, String receiverJid) {
this.files = files;
this.transfer = transfer;
this.receiverJid = receiverJid;
}
@Override
public void run() {
for (File file : files) {
try {
transfer.sendFile(file, file.getName());
} catch (XMPPException e) {
Logger.log(e);
return;
}
try {
while (!transfer.isDone()) {
String error;
if (transfer.getStatus() == Status.error) {
error = transfer.getError().getMessage();
} else {
error = null;
}
FileProgress fp = new FileProgress(getInternalService().getService().getServiceId(), transfer.getStreamID().hashCode(), file.getAbsolutePath(), transfer.getFileSize(), transfer.getAmountWritten(), false, receiverJid, error);
getInternalService().getService().getCoreService().fileProgress(fp);
Thread.sleep(1000);
}
FileProgress fp = new FileProgress(getInternalService().getService().getServiceId(), transfer.getStreamID().hashCode(), file.getAbsolutePath(), transfer.getFileSize(), transfer.getFileSize(), false, receiverJid, transfer.getError() != null ? transfer.getError().getMessage() : null);
getInternalService().getService().getCoreService().fileProgress(fp);
} catch (InterruptedException e) {
Logger.log(e);
}
}
}
}
private class IncomingFileRunnable implements Runnable {
private final String senderJid;
private final FileTransferRequest request;
private IncomingFileRunnable(String senderJid, FileTransferRequest request) {
this.senderJid = senderJid;
this.request = request;
}
@Override
public void run() {
Buddy buddy = getInternalService().getService().getEntityAdapter().rosterEntry2Buddy(getInternalService().getConnection().getRoster().getEntry(senderJid), getInternalService().getService().getProtocolUid(), getInternalService().getService().getContext(), getInternalService().getService().getServiceId());
File file = Utils.createLocalFileForReceiving(request.getFileName(), buddy, request.getFileSize());
IncomingFileTransfer transfer = request.accept();
try {
transfer.recieveFile(file);
} catch (XMPPException e1) {
Logger.log(e1);
}
try {
while (!transfer.isDone()) {
String error;
if (transfer.getStatus() == Status.error) {
error = transfer.getError().getMessage();
} else {
error = null;
}
FileProgress fp = new FileProgress(getInternalService().getService().getServiceId(), transfer.getStreamID().hashCode(), request.getFileName(), transfer.getFileSize(), transfer.getAmountWritten(), true, senderJid, error);
getInternalService().getService().getCoreService().fileProgress(fp);
Thread.sleep(1000);
}
FileProgress fp = new FileProgress(getInternalService().getService().getServiceId(), transfer.getStreamID().hashCode(), request.getFileName(), transfer.getFileSize(), transfer.getAmountWritten(), true, senderJid, transfer.getError() != null ? transfer.getError().getMessage() : null);
getInternalService().getService().getCoreService().fileProgress(fp);
} catch (InterruptedException e) {
Logger.log(e);
}
}
}
public void cancel(long messageId) {
FileTransferRequest request = fileTransfers.get(messageId);
if (request != null) {
request.reject();
fileTransfers.remove(messageId);
}
}
@Override
void onDisconnect() {
fileTransfers.clear();
}
}